package cn.hgy.domain.activity.service.trial.node;

import cn.hgy.domain.activity.model.entity.MarketProductEntity;
import cn.hgy.domain.activity.model.entity.TrialBalanceEntity;
import cn.hgy.domain.activity.model.valobj.GroupBuyActivityDiscountVO;
import cn.hgy.domain.activity.model.valobj.SkuVO;
import cn.hgy.domain.activity.service.discount.IDiscountCalculateService;
import cn.hgy.domain.activity.service.trial.AbstractGroupBuyMarketSupport;
import cn.hgy.domain.activity.service.trial.factory.DefaultActivityStrategyFactory;
import cn.hgy.domain.activity.service.trial.thread.QueryGroupBuyActivityDiscountVOThreadTask;
import cn.hgy.domain.activity.service.trial.thread.QuerySkuVODFromDBThreadTask;
import cn.hgy.types.enums.ResponseCode;
import cn.hgy.types.exception.AppException;
import cn.hgy.types.tree.StrategyHandler;
import com.alibaba.fastjson2.JSON;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Map;
import java.util.concurrent.*;

@Slf4j
@Service
@RequiredArgsConstructor
public class MarketNode extends AbstractGroupBuyMarketSupport<MarketProductEntity, DefaultActivityStrategyFactory.DynamicContext, TrialBalanceEntity> {

    // 线程池（用于并发查询数据）
    private final ThreadPoolExecutor threadPoolExecutor;
    // 正常流程终结点
    private final EndNode endNode;
    // 营销策略计算服务映射（key: 营销方案标识）
    private final Map<String, IDiscountCalculateService> discountCalculateServiceMap;
    private final ErrorNode errorNode;
    private final TagNode tagNode;

    /**
     * 拼团商品营销试算核心业务节点
     * 负责：1）异步数据加载 2）营销策略匹配 3）优惠金额试算 4）结果路由决策
     *
     * 关键能力：
     * 1. 多线程并发加载活动配置和商品数据
     * 2. 动态选择营销策略计算引擎
     * 3. 价格试算逻辑执行
     * 4. 试算结果有效性校验及路由
     */
    @Override
    protected void multiThread(MarketProductEntity requestParameter, DefaultActivityStrategyFactory.DynamicContext dynamicContext) throws ExecutionException, InterruptedException, TimeoutException {

        // 异步查询活动配置
        QueryGroupBuyActivityDiscountVOThreadTask queryGroupBuyActivityDiscountVOThreadTask = new QueryGroupBuyActivityDiscountVOThreadTask(requestParameter.getSource(), requestParameter.getChannel(), requestParameter.getGoodsId(), activityRepository);
        FutureTask<GroupBuyActivityDiscountVO> groupBuyActivityDiscountVOFutureTask = new FutureTask<>(queryGroupBuyActivityDiscountVOThreadTask);
        // 扔到线程池里就开始执行了
        threadPoolExecutor.execute(groupBuyActivityDiscountVOFutureTask);

        // 异步查询商品信息 - 在实际生产中，商品有同步库或者调用接口查询。这里暂时使用DB方式查询。
        QuerySkuVODFromDBThreadTask querySkuVODFromDBThreadTask = new QuerySkuVODFromDBThreadTask(requestParameter.getGoodsId(), activityRepository);
        FutureTask<SkuVO> skuVOFutureTask = new FutureTask<>(querySkuVODFromDBThreadTask);
        threadPoolExecutor.execute(skuVOFutureTask);

        // 写入上下文 - 对于一些复杂场景，获取数据的操作，有时候会在下N个节点获取，这样前置查询数据，可以提高接口响应效率
        dynamicContext.setGroupBuyActivityDiscountVO(groupBuyActivityDiscountVOFutureTask.get(timeout, TimeUnit.MINUTES));
        dynamicContext.setSkuVO(skuVOFutureTask.get(timeout, TimeUnit.MINUTES));

        log.info("拼团商品查询试算服务-MarketNode userId:{} 异步线程加载数据「GroupBuyActivityDiscountVO、SkuVO」完成", requestParameter.getUserId());
    }

    /**
     * 核心业务逻辑执行
     * 1. 校验上下文数据
     * 2. 选择营销策略计算服务
     * 3. 执行优惠计算
     * 4. 设置计算结果到上下文
     */
    @Override
    public TrialBalanceEntity doApply(MarketProductEntity requestParameter, DefaultActivityStrategyFactory.DynamicContext dynamicContext) throws Exception {
        log.info("拼团商品查询试算服务-MarketNode userId:{} requestParameter:{}", requestParameter.getUserId(), JSON.toJSONString(requestParameter));

        // 拿出上下文的数据
        GroupBuyActivityDiscountVO groupBuyActivityDiscountVO = dynamicContext.getGroupBuyActivityDiscountVO();
        if (null == groupBuyActivityDiscountVO) return router(requestParameter, dynamicContext);
        GroupBuyActivityDiscountVO.GroupBuyDiscount groupBuyDiscount = groupBuyActivityDiscountVO.getGroupBuyDiscount();

        SkuVO skuVO = dynamicContext.getSkuVO();
        if (null == groupBuyDiscount || null == skuVO) return router(requestParameter, dynamicContext);

        // 拼团优惠试算
        IDiscountCalculateService discountCalculateService = discountCalculateServiceMap.get(groupBuyDiscount.getMarketPlan());
        if (null == discountCalculateService) throw new AppException(ResponseCode.E0001.getCode(), ResponseCode.E0001.getInfo());

        // 折扣价格
        BigDecimal deductionPrice = discountCalculateService.calculate(requestParameter.getUserId(), skuVO.getOriginalPrice(), groupBuyDiscount);
        dynamicContext.setDeductionPrice(deductionPrice);

        return router(requestParameter, dynamicContext);
    }

    /**
     * 路由决策方法
     * 根据上下文数据完整性决定下一节点：
     * 1. 数据完整 → 正常终结点（EndNode）
     * 2. 数据缺失 → 异常终结点（ErrorNode）
     */
    @Override
    public StrategyHandler<MarketProductEntity, DefaultActivityStrategyFactory.DynamicContext, TrialBalanceEntity> get(MarketProductEntity requestParameter, DefaultActivityStrategyFactory.DynamicContext dynamicContext) {
        if (null == dynamicContext.getGroupBuyActivityDiscountVO() || null == dynamicContext.getSkuVO() || null == dynamicContext.getDeductionPrice()) return errorNode;
        return tagNode;
    }
}
